<template>
  <div>
    <el-form label-width="80px" :inline="false" size="default">
      <el-form-item label="SPU名称">
        <el-input v-model="spuInfo.spuName"></el-input>
      </el-form-item>
      <el-form-item label="品牌">
        <el-select placeholder="请选择品牌" v-model="spuInfo.tmId" clearable>
          <el-option v-for="item in TrademarkListAll" :key="item.id" :value="item.id" :label="item.tmName"></el-option>
        </el-select>
      </el-form-item>
      <el-form-item label="SPU描述">
        <el-input
            v-model="spuInfo.description"
            size="default"
            clearable
            type="textarea"
        ></el-input>
      </el-form-item>
      <el-form-item label="SPU图片">
        <el-upload
            v-model:file-list="SpuImageList"
            action="http://gmall-h5-api.atguigu.cn/admin/product/upload"
            list-type="picture-card"
            :on-preview="handlePictureCardPreview"
            :on-remove="handleRemove"
        >
          <el-icon>
            <ele-Plus/>
          </el-icon>
        </el-upload>

        <el-dialog v-model="dialogVisible">
          <img :src="dialogImageUrl" alt="Preview Image"/>
        </el-dialog>
      </el-form-item>
      <el-form-item label="销售属性">
        <el-select placeholder="请选择销售属性" v-model="saleAttrItem">
          <el-option v-for="item in unSaleAttrSelf" :key="item.id" :value="`${item.id}:${item.name}`"
                     :label="item.name"></el-option>
        </el-select>

        <el-button @click="addSaleAttrItem" icon="ele-Plus" type="primary" style="margin-left: 20px"
        >添加销售属性
        </el-button
        >
      </el-form-item>
      <el-form-item>
        <el-table border stripe :data="SaleAttrSelfList">
          <el-table-column type="index" width="80" label="序号"/>
          <el-table-column label="属性名" prop="saleAttrName"></el-table-column>
          <el-table-column label="属性值名称列表">
            <template #default="{row}">
              <el-tag @close="removeSaleAttrValue(row,index)" closable v-for="(item,index) in row.spuSaleAttrValueList"
                      :key="item.id">{{
                  item.saleAttrValueName
                }}
              </el-tag>
              <el-button @click="toInput(row)" v-if="!row.isEdit" size="small" icon="ele-Plus">添加销售属性值
              </el-button>
              <el-input v-model="saleAttrValueItem" ref="inputEle" @blur="toButton(row)" v-else size="small"></el-input>
            </template>
          </el-table-column>
          <el-table-column label="操作">
            <template #default="{row,$index}">
              <el-button @click="removeSaleAttr($index)" title="删除销售属性" size="small" type="danger"
                         icon="ele-Delete"></el-button>
            </template>
          </el-table-column>
        </el-table>
      </el-form-item>
      <el-form-item>
        <el-button @click="submit" type="primary">保存</el-button>
        <el-button @click="emit('changeType', 0)">取消</el-button>
      </el-form-item>
    </el-form>
  </div>
</template>

<script lang="ts">
import {defineComponent} from "vue";

export default defineComponent({
  name: "SpuForm",
});
</script>

<script setup lang="ts">
import {
  type baseSaleAttrListType, reqAddSpuAsync, reqBaseSaleAttrList, reqSaleAttrSelf, reqSpuImageList, reqUpdateSpuAsync,
  type SpuItemType,
  type spuSaleAttrItemType,
  type spuSaleAttrListType,
  type spuSaleImgListType
} from "@/api/spu";
import {computed, nextTick, onMounted, ref} from "vue";
import type {UploadProps} from "element-plus";
import type {TrademarkListAllType} from "@/api/trademark";
import {reqGetTrademarkListAllAsync} from "@/api/trademark";
import {ElMessage} from "element-plus";

// 获取自定义事件 控制组件隐藏
const emit = defineEmits<{
  (event: 'changeType', type: number): void
}>()
// 获取父组件传递过来的值
const props = defineProps<{
  spuInfo: SpuItemType
}>()

const dialogImageUrl = ref("");
const dialogVisible = ref(false);

/*因为数据双向绑定了  删除的时候数据会改变  添加的时候数据会改变*/

// 删除图片的回调
const handleRemove: UploadProps["onRemove"] = (uploadFile, uploadFiles) => {
  console.log(uploadFile, uploadFiles);
};
// 上传图片的回调
const handlePictureCardPreview: UploadProps["onPreview"] = (uploadFile) => {
  dialogImageUrl.value = uploadFile.url!;
  dialogVisible.value = true;
};

// 保存所有的品牌列表数据
const TrademarkListAll = ref<TrademarkListAllType>([])
// 保存所有销售属性列表
const SaleAttrListAll = ref<baseSaleAttrListType>([])
// 保存当前spuId下的所有图片列表
const SpuImageList = ref<spuSaleImgListType>([])
// 保存当前spuId获取自己的销售属性列表
const SaleAttrSelfList = ref<spuSaleAttrListType>([])

// 组件挂载时 判断父组件传递的 spuInfo也就是Spu销售的属性 是否有值
// 从而查看是修改spu操作还是增加spu操作
onMounted(async () => {
  try {
    if (props.spuInfo.id) {  // 修改
      // 修改操作  需要发送四个请求
      const p1 = reqGetTrademarkListAllAsync()  //  所有品牌列表
      const p2 = reqBaseSaleAttrList()  // 所有销售属性列表
      const p3 = reqSpuImageList(props.spuInfo.id)  // 根据spuId获取图片列表
      const p4 = reqSaleAttrSelf(props.spuInfo.id)  // 根据spuId获取自己的销售属性列表

      // 四个请求一起发 四个都成功则成功 返回一个 Promise value是一个数组
      const result = await Promise.all([p1, p2, p3, p4])
      TrademarkListAll.value = result[0]
      SaleAttrListAll.value = result[1]
      SpuImageList.value = result[2]
      SaleAttrSelfList.value = result[3]

      // 因为显示图片墙需要 name和url属性 所以需要额外添加  后续提交数据 需要剔除
      SpuImageList.value.forEach(item => {
        item.name = item.imgName;
        item.url = item.imgUrl
      })
    } else {  // 添加
      // 添加操作  需要发送两个请求
      const p1 = reqGetTrademarkListAllAsync()  //  所有品牌列表
      const p2 = reqBaseSaleAttrList()  // 所有销售属性列表

      // 两个请求一起发 两个个都成功则成功 返回一个 Promise value是一个数组
      const result = await Promise.all([p1, p2])
      TrademarkListAll.value = result[0]
      SaleAttrListAll.value = result[1]
    }
  } catch (e: any) {
    ElMessage.error(e.message)
  }
})

// 计算获取没有选择的销售属性  销售属性选择框是选择的是 没有选择的销售属性
const unSaleAttrSelf = computed(() => {
  return SaleAttrListAll.value.filter(item => {  // 使用所有的 对比自己拥有的 过滤出 自己没有的
    return !SaleAttrSelfList.value.some(selfItem => {  // 返回不重复的
      return item.name === selfItem.saleAttrName  // 返回c重复的
    })
  })
})

// 保存选择的销售属性框的 销售属性
const saleAttrItem = ref('')

// 添加销售属性到自己的销售属性列表中
const addSaleAttrItem = () => {
  // 分离出 保存的 销售属性
  const [id, name] = saleAttrItem.value.split(':')

  // 添加销售属性到自己的销售属性列表
  SaleAttrSelfList.value.push({
    baseSaleAttrId: +id, //当前销售属性在基础销售属性列表中的id
    saleAttrName: name, //当前销售属性的名称
    spuId: props.spuInfo.id,  //当前销售属性所在的spuId
    spuSaleAttrValueList: [],  //当前整体的Spu销售的属性值列表数据的限制
    isEdit: false
  })

  // 清空选择框的销售属性
  saleAttrItem.value = ''
}
// 获取输入属性值的input的DOM节点
const inputEle = ref<HTMLInputElement>()

// 添加添加属性值按钮 切换成 输入模式
const toInput = (row: spuSaleAttrItemType) => {
  //  切换成 输入模式
  row.isEdit = true

  // 自动获取焦点
  nextTick(() => {
    inputEle.value?.focus()
  })
}

// 收集input 输入框 输入的销售属性值
const saleAttrValueItem = ref('')

// 输入模式的input 失焦的时候切换成 查看模式
const toButton = (row: spuSaleAttrItemType) => {
  // 切换成 查看模式
  row.isEdit = false

  if (!saleAttrValueItem.value) return ElMessage.error("输入的销售属性值不能为空")

  // 查看添加的销售属性值 是否 重复
  const isRepeat = row.spuSaleAttrValueList.some(item => {
    return item.saleAttrValueName === saleAttrValueItem.value
  })

  // 如果重复
  if (isRepeat) {
    // 清空 输入框 输入的销售属性值
    saleAttrValueItem.value = ''

    return ElMessage.error('您输入的值重复了')
  }

  // 并将需要添加的销售属性值保存在销售属性值列表中
  row.spuSaleAttrValueList.push({
    baseSaleAttrId: row.baseSaleAttrId,  //当前销售属性值所在的销售属性的id  添加的时候后台不需要这个值
    isChecked: '',  //当前销售属性值是否是被选中状态  添加的时候后台不需要这个值
    saleAttrName: row.saleAttrName, //所在的销售属性的名称
    saleAttrValueName: saleAttrValueItem.value, //所在的销售属性值的名称
    spuId: props.spuInfo.id //当前销售属性所在的spu的id  添加的时候后台不需要这个值
  })

  // 清空 输入框 输入的销售属性值
  saleAttrValueItem.value = ''
}

// 删除销售属性值
const removeSaleAttrValue = (row: spuSaleAttrItemType, index: number) => {
  row.spuSaleAttrValueList.splice(index, 1)
}

// 删除销售属性
const removeSaleAttr = (index: number) => {
  SaleAttrSelfList.value.splice(index, 1)
}

// 提交功能
const submit = async () => {
// 处理销售属性值列表不需要的数据 isEdit
  SaleAttrSelfList.value.forEach(item => {
    delete item.isEdit
  })
  // 处理图片列表中不需要的数据和重写需要的数据的属性名  后台添加/修改图片列表只需要 imgName和imgUrl
  SpuImageList.value = SpuImageList.value.map(item => {
    if (item.response) {  // 这是新添加的图片 格式不对 需要剔除不需要的
      return {
        spuId: props.spuInfo.id,   // 添加在那个 spu值 的下面的 spuId
        imgName: item.response.name,  // 图片名
        imgUrl: item.response.data,   // 图片地址
      }
    } else {
      delete item.name;   // 添加和修改的照片墙需要  后续剔除
      delete item.url;    // 添加和修改的照片墙需要   后续剔除
      delete item.response;    // 用于查看 是否是新添加的图片 后续剔除
      return item
    }
  })

  // 将整理好的数据 一并交给 保存添加的数据/修改的数据的 变量中
  props.spuInfo.spuSaleAttrList = SaleAttrSelfList.value as [];
  props.spuInfo.spuImageList = SpuImageList.value as [];

  // 发送请求
  try {
    if (props.spuInfo.id) {  // 代表发送修改请求
      await reqUpdateSpuAsync(props.spuInfo)
      ElMessage.success('修改成功')
    } else {  // 代表发送添加请求
      await reqAddSpuAsync(props.spuInfo)
      ElMessage.success('添加成功')
    }
    // 跳转到spuList
    emit('changeType', 0)
  } catch (e: any) {
    ElMessage.error(e.message)
    // 跳转到spuList
    emit('changeType', 0)
  }
}
</script>

<style scoped></style>
